#include "liverecorder.h"
#include "captchaassisttask.h"
#include "getattentionstask.h"
#include "getliveinfohelper.h"
#include "libs/controls/toastlabel.h"
#include "libs/core/model/attentionmodel.h"
#include "libs/core/model/livemodel.h"
#include "libs/core/model/model.h"
#include "libs/core/model/presentermodel.h"
#include "liverecorderview.h"
#include "liveviewmanager.h"
#include "presentermonitor.h"
#include "recordtaskmanager.h"
#include "services/yingceservice.h"
#include "usersettings.h"
#include "utils/utils.h"
#include "yingce.h"
#include <QAction>
#include <QDesktopServices>
#include <QIcon>
#include <QMessageBox>
#include <QPixmap>
#include <QTimer>
#include <QUrl>

LiveRecorder::LiveRecorder(yc::ExtensionManager* ext_mgr, QWidget* container)
    : yc::Extension { ext_mgr, container }
{
    live_view_manager_.reset(new LiveViewManager(container));
    get_live_info_helper_ = new GetLiveInfoHelper(live_view_manager_.get(), this);
    record_task_manager_ = new RecordTaskManager(this);
    monitor_ = new PresenterMonitor(this, this);
    view_ = new LiveRecorderView(this, container);

    // 实时检测
    QIcon icon;
    icon.addFile(QString::fromLatin1(":/images/switch-OFF.png"), QSize(), QIcon::Normal,
                 QIcon::Off);
    icon.addFile(QString::fromLatin1(":/images/switch-ON.png"), QSize(), QIcon::Normal, QIcon::On);
    auto_check_action_ = new QAction(tr("Auto Check"), this);
    auto_check_action_->setToolTip(tr("Auto Check"));
    auto_check_action_->setCheckable(true);
    auto_check_action_->setIcon(icon);
    connect(auto_check_action_, &QAction::triggered, this, [this](bool checked) {
        if (checked) {
            if (YingCe::instance()->model()->attentionModel()->autoCheckCount()
                < UserSettings::instance().recorderSettings().realtime_monitor_count) {
                changeAttentionAutoCheck(view_->currentAttention(), true);
            } else {
                yc::ToastLabel::showMessage(
                        tr("Achieve the maximum number of real-time detections"), view_);
            }
        } else {
            changeAttentionAutoCheck(view_->currentAttention(), false);
        }
    });
    // 自动录制
    auto_record_action_ = new QAction(tr("Auto Record"), this);
    auto_record_action_->setToolTip(tr("Auto Record"));
    auto_record_action_->setCheckable(true);
    auto_record_action_->setIcon(icon);
    connect(auto_record_action_, &QAction::triggered, this, [this](bool checked) {
        changeAttentionAutoRecord(view_->currentAttention(), checked);
    });
    // 主播本地目录
    open_dir_action_ = new QAction(tr("Open Dir"), this);
    open_dir_action_->setIcon(QIcon(":/images/folder.png"));
    open_dir_action_->setIconVisibleInMenu(false);
    connect(open_dir_action_, &QAction::triggered, this, [this](bool checked) {
        Q_UNUSED(checked)
        utils::showFileInFolder(
                LiveRecorder::createAttentionDirectory(view_->currentAttention()).absolutePath());
    });
    // 更改所属行业
    change_category_action_ = new QAction(tr("Change Category"), this);
    connect(change_category_action_, &QAction::triggered, this, [this](bool checked) {
        Q_UNUSED(checked)
        changeAttentionCategory(view_->currentAttention(), 10);
    });
    // 主播个人主页
    home_action_ = new QAction(tr("Home"), this);
    home_action_->setIcon(QIcon(":/images/home.png"));
    home_action_->setIconVisibleInMenu(false);
    connect(home_action_, &QAction::triggered, this, [this](bool checked) {
        Q_UNUSED(checked)
        if (auto a = YingCe::instance()->model()->attentionModel()->attention(
                    view_->currentAttention())) {
            if (auto p = YingCe::instance()->model()->presenterModel()->presenter(a->presenter)) {
                const auto entry = YingCe::instance()->model()->liveModel()->webEntry(p->platform);
                QDesktopServices::openUrl(
                        QUrl { QString(entry.profile_url).arg(p->platform_sec_uid) });
            }
        }
    });

    // 获取attentions
    QTimer::singleShot(25, this, [this] {
        auto t = new GetAttentionsTask(this);
        connect(t, &GetAttentionsTask::aboutToStart, view_, &LiveRecorderView::showLoading);
        connect(t, &GetAttentionsTask::failed, view_, &LiveRecorderView::hideLoading);
        connect(t, &GetAttentionsTask::finished, view_, &LiveRecorderView::hideLoading);
        connect(t, &GetAttentionsTask::finished, this, &LiveRecorder::onGetAttentions);
        connect(t, &GetAttentionsTask::failed, monitor_, &PresenterMonitor::start);
        t->start();
    });
}

LiveRecorder::~LiveRecorder()
{
    record_task_manager_->termiateAll();
    monitor_->stop();
    delete monitor_;
    delete view_;
    live_view_manager_.reset(nullptr);
}

yc::ExtensionView* LiveRecorder::view()
{
    return view_;
}

bool LiveRecorder::isRecording() const
{
    return record_task_manager_->count() > 0;
}

void LiveRecorder::changeAttentionAutoCheck(int id, bool auto_check)
{
    auto am = YingCe::instance()->model()->attentionModel();
    if (!auto_check
        || am->autoCheckCount()
                < UserSettings::instance().recorderSettings().realtime_monitor_count) {
        if (auto a = am->attention(id)) {
            am->setAutoCheck(id, auto_check);
            monitor_->setRealtime(a->presenter, auto_check);

            YingCeService::instance()->changeAttentionAutoCheck(
                    id, auto_check,
                    yc::ResponseHandler(
                            this, [](const yc::Request& request, const yc::Response& response) {
                                if (response.status() != yc::OK_CODE) {
                                    qDebug() << response.status() << response.msg();
                                }
                            }));
        }
    }
}

void LiveRecorder::changeAttentionAutoRecord(int id, bool auto_record)
{
    auto am = YingCe::instance()->model()->attentionModel();
    if (!auto_record
        || am->autoRecordCount() < UserSettings::instance().recorderSettings().recorder_count) {
        am->setAutoRecord(id, auto_record);

        YingCeService::instance()->changeAttentionAutoRecord(
                id, auto_record,
                yc::ResponseHandler(this,
                                    [](const yc::Request& request, const yc::Response& response) {
                                        if (response.status() != yc::OK_CODE) {
                                            qDebug() << response.status() << response.msg();
                                        }
                                    }));
    }
}

void LiveRecorder::changeAttentionCategory(int id, int category)
{
    YingCeService::instance()->changeAttentionCategory(
            id, category,
            yc::ResponseHandler(
                    this, [id, category](const yc::Request& request, const yc::Response& response) {
                        if (response.status() == yc::OK_CODE) {
                            YingCe::instance()->model()->attentionModel()->setCategory(id,
                                                                                       category);
                        } else {
                            qDebug() << response.status() << response.msg();
                        }
                    }));
}

void LiveRecorder::deleteAttentions(const QList<int>& ids)
{
    YingCeService::instance()->deleteAttentions(
            ids,
            yc::ResponseHandler(this,
                                [ids](const yc::Request& request, const yc::Response& response) {
                                    if (response.status() == yc::OK_CODE) {
                                        auto am = YingCe::instance()->model()->attentionModel();
                                        for (int id : ids) {
                                            am->remove(id);
                                        }
                                    } else {
                                        qDebug() << response.status() << response.msg();
                                    }
                                }));
}

void LiveRecorder::startRecording(int attention)
{
    if (!record_task_manager_->isRunning(attention)) {
        if (record_task_manager_->count()
            < UserSettings::instance().recorderSettings().recorder_count) {
            record_task_manager_->start(attention);
        } else {
            yc::ToastLabel::showMessage(tr("Achieve the maximum number of recorder"), view_);
        }
    }
}

QDir LiveRecorder::createAttentionDirectory(int id)
{
    QDir video_dir { UserSettings::instance().recorderSettings().video_save_dir };
    if (auto a = YingCe::instance()->model()->attentionModel()->attention(id)) {
        if (auto p = YingCe::instance()->model()->presenterModel()->presenter(a->presenter)) {
            if (video_dir.exists(p->platform_id) || video_dir.mkdir(p->platform_id)) {
                video_dir.cd(p->platform_id);
                return video_dir;
            }
        }
    }
    return video_dir;
}

bool LiveRecorder::containsKuaiShouAttentions()
{
    bool kuaishow_found = false;
    auto am = YingCe::instance()->model()->attentionModel();
    auto pm = YingCe::instance()->model()->presenterModel();
    for (auto i : am->attentions()) {
        if (auto p = pm->presenter(i->presenter)) {
            if (p->platform == yc::KUAISHOW_PLATFORM_TYPE) {
                kuaishow_found = true;
                break;
            }
        }
    }
    return kuaishow_found;
}

void LiveRecorder::onGetAttentions()
{
    if (containsKuaiShouAttentions()) {
        auto ret = QMessageBox::question(
                view_, tr("Captcha Assist"),
                tr("To ensure the security of your visit, a slider verification needs to be "
                   "completed. After clicking 'Ok', the Kuaishou verification page will "
                   "automatically open. You just need to "
                   "drag the slider to complete the verification. There is no need to log in to "
                   "your account. Thank you for your cooperation!"),
                QMessageBox::Ok | QMessageBox::Close, QMessageBox::Ok);
        if (ret == QMessageBox::Ok) {
            auto t = new CaptchaAssistTask(this, this);
            connect(t, &CaptchaAssistTask::finished, monitor_, &PresenterMonitor::start);
            connect(t, &CaptchaAssistTask::failed, monitor_, &PresenterMonitor::start);
            t->start();
            return;
        }
    }

    // 开启状态监测
    monitor_->start();
}
